package alipay

import (
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gogap/logs"
	"github.com/shopspring/decimal"
	"go.uber.org/zap"
	"io/ioutil"
	"log"
	"net/url"
	"strconv"
	"time"
	"yundian/internel/app/dao"
	"yundian/internel/app/dao/memberdao"
	"yundian/internel/app/helper"
	"yundian/internel/app/helper/request"
	"yundian/internel/app/logic"
	"yundian/internel/app/models/automate"
	"yundian/internel/app/models/devices"
	"yundian/internel/app/models/goods"
	"yundian/internel/app/models/membermodel"
	"yundian/internel/app/models/orders"
	"yundian/internel/app/models/ordersmonthly"
	"yundian/internel/app/models/placemodel"
	"yundian/internel/app/models/ploys"
	"yundian/internel/app/models/prices"
	"yundian/internel/app/models/room"
	"yundian/internel/app/models/users"
	"yundian/internel/pkg/alipay"
	"yundian/internel/pkg/dingo"
	"yundian/internel/pkg/dingo/global"
)

// 周期扣款 自动续费支付通知
func HandleAliPayNotifyAgreementAuto(c *gin.Context) {
	bm, err := alipay.ParseNotifyToBodyMap(c.Request)
	if err != nil {
		log.Println("支付宝统一下单,解析请求参数失败", err.Error())
		return
	}
	log.Println("异步通知数据", bm)

	file, err := ioutil.ReadFile(global.Cfg.Ali.PublicKey)
	if err != nil {
		log.Println("支付宝统一下单,获取应用密钥失败", err.Error())
		return
	}

	var bodyMap alipay.BodyMap
	// aliPayPublicKey 支付宝公钥证书
	aliPayPublicKey := string(file)
	ok, err := alipay.VerifySign(aliPayPublicKey, bm)
	if err != nil || !ok {
		log.Println("验签失败", err.Error())
		return
	}
	bs, err := json.Marshal(bm)
	if err = json.Unmarshal(bs, &bodyMap); err != nil {
		log.Println("参数转换错误 ,HandleAliPayNotifySing", err.Error())
		return
	}

	if bodyMap.Get("refund_fee") != "" {
		c.JSON(200, "success")
	}

	orderInfo, _ := dao.NewOrderAutoRenewDao().GetAutoOrderByTradeNo(bodyMap.Get("out_trade_no"))
	if orderInfo.Id == 0 {
		return
	}

	orderParams := &ordersmonthly.OrderMonthlyModel{
		OrderMonthlyDB: ordersmonthly.OrderMonthlyDB{
			RenewStatus:  helper.TypeNumOrderMonthlyRenewStatusNormal,
			Status:       helper.TypeNumOrderMonthlyStatusCompletion,
			TradeNo:      bodyMap.Get("out_trade_no"),
			ThirdTradeNo: bodyMap.Get("trade_no"),
		},
		PayTime: time.Now().Format("2006-01-02 15:04:05"),
	}

	if updateResult := dao.NewOrderAutoRenewDao().UpdateAutoRenewMonthlyByAgreementNo(orderParams); updateResult.Err != nil {
		logs.Error("周期扣款订单-已续费状态更新", updateResult.Err)
		return
	}

	if orderResult := dao.NewOrderAutoRenewDao().UpdateAutoRenewMonthlyPay(orderParams); orderResult.Err != nil {
		logs.Error("周期扣款订单-续费订单更新", orderResult.Err)
		return
	}

	c.JSON(200, "success")
}

// 周期扣款签约支付通知
func HandleAliPayNotifyAgreement(c *gin.Context) {
	bm, err := alipay.ParseNotifyToBodyMap(c.Request)
	if err != nil {
		log.Println("支付宝统一下单,解析请求参数失败", err.Error())
		return
	}
	log.Println("异步通知数据", bm)

	file, err := ioutil.ReadFile(global.Cfg.Ali.PublicKey)
	if err != nil {
		log.Println("支付宝统一下单,获取应用密钥失败", err.Error())
		return
	}

	var bodyMap alipay.BodyMap
	// aliPayPublicKey 支付宝公钥证书
	aliPayPublicKey := string(file)
	ok, err := alipay.VerifySign(aliPayPublicKey, bm)
	if err != nil || !ok {
		log.Println("验签失败", err.Error())
		return
	}
	bs, err := json.Marshal(bm)
	if err = json.Unmarshal(bs, &bodyMap); err != nil {
		log.Println("参数转换错误 ,HandleAliPayNotifyAgreement", err.Error())
		return
	}
	day, _ := strconv.Atoi(global.Cfg.Ali.AutoPayDay)
	h, _ := time.ParseDuration(fmt.Sprintf("%dh", 24*day))
	orderParams := &ordersmonthly.OrderMonthlyModel{
		OrderMonthlyDB: ordersmonthly.OrderMonthlyDB{
			RenewStatus: 1,
			AgreementNo: bodyMap.Get("agreement_no"),
			TradeNo:     bodyMap.Get("external_agreement_no"),
		},
		PayTime:   time.Now().Format("2006-01-02 15:04:05"),
		RenewTime: time.Now().Add(h).Format("2006-01-02"),
		//RenewTime: utils.AddDate(time.Now(), 0, 1).Format("2006-01-02 15:04:05"),
	}

	// 解约通知
	if bodyMap.Get("notify_type") == "dut_user_unsign" {
		orderParams = &ordersmonthly.OrderMonthlyModel{
			OrderMonthlyDB: ordersmonthly.OrderMonthlyDB{
				RenewStatus: 3,
				TradeNo:     bodyMap.Get("external_agreement_no"),
			},
		}
	}

	if err := dao.NewOrderAutoRenewDao().UpdateAutoRenewMonthly(orderParams).Err; err != nil {
		logs.Error("周期扣款订单", err)
		return
	}

	c.JSON(200, "success")
}

// 周期扣款签约支付通知
func HandleAliPayNotifySing(c *gin.Context) {
	logs.Info("测试===============>进入HandleAliPayNotifySing")
	bm, err := alipay.ParseNotifyToBodyMap(c.Request)
	if err != nil {
		log.Println("支付宝统一下单,解析请求参数失败", err.Error())
		return
	}
	log.Println("异步通知数据", bm)

	file, err := ioutil.ReadFile(global.Cfg.Ali.PublicKey)
	if err != nil {
		log.Println("支付宝统一下单,获取应用密钥失败", err.Error())
		return
	}

	var bodyMap alipay.BodyMap
	// aliPayPublicKey 支付宝公钥证书
	aliPayPublicKey := string(file)
	ok, err := alipay.VerifySign(aliPayPublicKey, bm)
	if err != nil || !ok {
		log.Println("验签失败", err.Error())
		return
	}
	bs, err := json.Marshal(bm)
	if err = json.Unmarshal(bs, &bodyMap); err != nil {
		log.Println("参数转换错误 ,HandleAliPayNotifySing", err.Error())
		return
	}

	if bodyMap.Get("refund_fee") != "" {
		c.JSON(200, "success")
	}

	orderParams := &ordersmonthly.OrderMonthlyModel{
		OrderMonthlyDB: ordersmonthly.OrderMonthlyDB{
			Status:       5,
			TradeNo:      bodyMap.Get("out_trade_no"),
			ThirdTradeNo: bodyMap.Get("trade_no"),
		},
		PayTime: time.Now().Format("2006-01-02 15:04:05"),
		//RenewTime: time.Now().Format("2006-01-02 15:04:05"),
	}
	_ = dao.NewOrderAutoRenewDao().UpdateAutoRenewMonthlyPay(orderParams)

	//client := logic.NewAliPayOrderLogic()
	//client.TradeNo = bodyMap.Get("out_trade_no")
	//agreementInfo, err := client.ExecUserAgreementSign()
	//logs.Info("agreementInfo", agreementInfo)
	//logs.Info("agreementInfo-err", err)

	//if orderResult.Err != nil {
	//	logs.Error("周期扣款订单", orderResult.Err)
	//	return
	//}

	//生成订单
	resultNotifyOk := DepositPayResultNotifyNoDraw(bodyMap)
	// 处理通知
	if resultNotifyOk {
		// 处理成功返回值设置
		c.JSON(200, "success")
		return
	}

	//c.JSON(200, "success")
}

func HandleAliPayNotify(c *gin.Context) {

	// 解析请求参数
	bm, err := alipay.ParseNotifyToBodyMap(c.Request)
	if err != nil {
		log.Println("支付宝统一下单,解析请求参数失败", err.Error())
		return
	}
	log.Println("异步通知数据", bm)

	file, err := ioutil.ReadFile(global.Cfg.Ali.PublicKey)
	if err != nil {
		log.Println("支付宝统一下单,获取应用密钥失败", err.Error())
		return
	}

	var bodyMap alipay.BodyMap
	//aliPayPublicKey 支付宝公钥证书
	aliPayPublicKey := string(file)
	// 验签
	ok, err := alipay.VerifySign(aliPayPublicKey, bm)
	if err != nil {
		log.Println("验签失败", err.Error())
		return
	}
	bs, err := json.Marshal(bm)
	if ok {
		err = json.Unmarshal(bs, &bodyMap)
		if err != nil {
			log.Println("参数转换错误 ,HandleAliPayNotify", err.Error())
			return
		}

		//生成订单
		fmt.Println("DepositPayResultNotify", bodyMap.Get("out_trade_no"))
		resultNotifyOk := DepositPayResultNotify(bodyMap, 1)
		// 处理通知
		if resultNotifyOk {
			//orderInfo := dao.NewOrderDao().WxGetOrderInfoByTradeNo(bodyMap.Get("out_trade_no")).Unwrap().(*orders.OrderModel)
			//orderLogic := logic.NewAliPayOrderLogic()
			//
			//respData, err := orderLogic.AliPayOrderMessage(orderInfo)
			//fmt.Println("AliPayOrderMessage", respData, err)
			//
			//go func() {
			//	time.Sleep(60 * time.Second)
			//	respData, err := orderLogic.AliPaySubscribeMessage(orderInfo)
			//	fmt.Println("AliPaySubscribeMessage", respData, err)
			//}()

			// 处理成功返回值设置
			c.JSON(200, "success")
			return
		}

	}
}

func HandleAliPayNotifyNoDraw(c *gin.Context) {

	// 解析请求参数
	bm, err := alipay.ParseNotifyToBodyMap(c.Request)
	if err != nil {
		log.Println("支付宝统一下单,解析请求参数失败", err.Error())
		return
	}
	log.Println("异步通知数据", bm)

	file, err := ioutil.ReadFile(global.Cfg.Ali.PublicKey)
	if err != nil {
		log.Println("支付宝统一下单,获取应用密钥失败", err.Error())
		return
	}

	var bodyMap alipay.BodyMap
	//aliPayPublicKey 支付宝公钥证书
	aliPayPublicKey := string(file)
	// 验签
	ok, err := alipay.VerifySign(aliPayPublicKey, bm)
	if err != nil {
		log.Println("验签失败", err.Error())
		return
	}
	bs, err := json.Marshal(bm)
	if ok {
		err = json.Unmarshal(bs, &bodyMap)
		if err != nil {
			log.Println("参数转换错误 ,HandleAliPayNotify", err.Error())
			return
		}

		//生成订单
		fmt.Println("DepositPayResultNotify", bodyMap.Get("out_trade_no"))
		resultNotifyOk := DepositPayResultNotify(bodyMap, 0)
		// 处理通知
		if resultNotifyOk {
			//orderInfo := dao.NewOrderDao().WxGetOrderInfoByTradeNo(bodyMap.Get("out_trade_no")).Unwrap().(*orders.OrderModel)
			//orderLogic := logic.NewAliPayOrderLogic()
			//
			//respData, err := orderLogic.AliPayOrderMessage(orderInfo)
			//fmt.Println("AliPayOrderMessage", respData, err)
			//
			//go func() {
			//	time.Sleep(60 * time.Second)
			//	respData, err := orderLogic.AliPaySubscribeMessage(orderInfo)
			//	fmt.Println("AliPaySubscribeMessage", respData, err)
			//}()

			// 处理成功返回值设置
			c.JSON(200, "success")
			return
		}

	}
}

// 支付结果通知 业务逻辑处理    返回值 ： true处理成功通知
func DepositPayResultNotify(resultData alipay.BodyMap, openIsDraw int) bool {
	count := dao.NewOrderDao().
		CountOrderByTradeNo(resultData.Get("out_trade_no")).
		Unwrap().(int64)

	// 验证订单是否已经处理
	if count > 0 { // 订单已处理
		return true
	}

	memInfo := memberdao.NewMemberDao().
		GetMemberInfoByOpenidAndAppId(resultData.Get("buyer_open_id"), resultData.Get("app_id")).
		Unwrap().(*membermodel.MembersModel)

	//解密公共参数
	params, err := url.ParseQuery(resultData.Get("passback_params"))
	if err != nil {
		log.Println("解密公共参数失败", err.Error())
		return false
	}
	paramMap := map[string]string{}
	for key, value := range params {
		paramMap[key] = value[0]
	}

	devInfo := dao.NewDeviceDao().FetchDeviceInfoWithType(paramMap["device_info"]).Unwrap().(*devices.DeviceType)
	ruleInfo := dao.NewPricesDao().GetPriceDetail(paramMap["attach"]).Unwrap().(*prices.PriceModel) // 获取产品ID对应的价格规则配置
	//ployInfo := dao.NewPloysDao().GetPlacePloyInfo(devInfo.PlaceId, devInfo.SharedMode).Unwrap().(*ploys.PloyModel) // 获取商户最新奖励规则配置

	var money int64

	if devInfo.FeeMode == 1 { // 计时
		money = ruleInfo.Deposit
	} else { // 套餐
		money = ruleInfo.PayMoney // 支付套餐价
	}
	//测试版本暂时注释掉
	log.Println("打印测试数据，价格不一致", money)
	log.Println("========resultData", resultData)
	log.Println("========devInfo", devInfo)
	log.Println("========memInfo", memInfo)
	// 验证订单价格是否正确
	orderCreateStatus := CreateOrder(
		resultData,
		devInfo,
		memInfo, openIsDraw)
	// 更新设备 true 更新成功  false 更新失败
	_ = UpdateDeviceInfo(paramMap["device_info"]) //更新设备信息 - 成功或失败不重要

	return orderCreateStatus
}

func DepositPayResultNotifyNoDraw(resultData alipay.BodyMap) bool {
	count := dao.NewOrderDao().
		CountOrderByTradeNo(resultData.Get("out_trade_no")).
		Unwrap().(int64)

	// 验证订单是否已经处理
	if count > 0 { // 订单已处理
		return true
	}

	memInfo := memberdao.NewMemberDao().
		GetMemberInfoByOpenidAndAppId(resultData.Get("buyer_open_id"), resultData.Get("app_id")).
		Unwrap().(*membermodel.MembersModel)

	//解密公共参数
	params, err := url.ParseQuery(resultData.Get("passback_params"))
	if err != nil {
		log.Println("解密公共参数失败", err.Error())
		return false
	}
	paramMap := map[string]string{}
	for key, value := range params {
		paramMap[key] = value[0]
	}

	omInfo, _ := dao.NewOrderAutoRenewDao().GetAutoOrderByTradeNo(resultData.Get("out_trade_no"))
	devInfo := dao.NewDeviceDao().FetchDeviceInfoWithType(omInfo.DeviceSn).Unwrap().(*devices.DeviceType)
	ruleInfo := dao.NewPricesDao().GetPriceDetail(omInfo.ProductId).Unwrap().(*prices.PriceModel) // 获取产品ID对应的价格规则配置
	//ployInfo := dao.NewPloysDao().GetPlacePloyInfo(devInfo.PlaceId, devInfo.SharedMode).Unwrap().(*ploys.PloyModel) // 获取商户最新奖励规则配置

	var money int64

	if devInfo.FeeMode == 1 { // 计时
		money = ruleInfo.Deposit
	} else { // 套餐
		money = ruleInfo.PayMoney // 支付套餐价
	}
	//测试版本暂时注释掉
	log.Println("打印测试数据，价格不一致", money)
	log.Println("========resultData", resultData)
	log.Println("========devInfo", devInfo)
	log.Println("========memInfo", memInfo)
	// 验证订单价格是否正确
	orderCreateStatus := CreateOrderSingNoDraw(
		resultData,
		devInfo,
		memInfo, omInfo.ProductId)
	// 更新设备 true 更新成功  false 更新失败
	_ = UpdateDeviceInfo(paramMap["device_info"]) //更新设备信息 - 成功或失败不重要

	return orderCreateStatus
}

// CreateOrder 生成订单 todo 需要添加KaUserId
func CreateOrder(respData alipay.BodyMap, devInfo *devices.DeviceType, memInfo *membermodel.MembersModel, openIsDraw int) bool {
	stamp, _ := time.ParseInLocation("2006-01-02 15:04:05", respData.Get("notify_time"), time.Local)
	moneyFloat, _ := strconv.ParseFloat(respData.Get("total_amount"), 64)
	money := int64(moneyFloat * 100)
	payMoneyFloat, _ := strconv.ParseFloat(respData.Get("buyer_pay_amount"), 64)
	payMoney := int64(payMoneyFloat * 100)
	ployInfo := dao.NewPloysDao().GetPlacePloyInfo(devInfo.PlaceId, devInfo.SharedMode).Unwrap().(*ploys.PloyModel) // 获取商户最新奖励规则配置

	fundBillList := &struct {
		Amount string `json:"amount"`
		FundChannel   string `json:"fundChannel"`
	}{}
	_ = json.Unmarshal([]byte(respData.Get("fund_bill_list")), fundBillList)
	var phone string
	if memInfo.Phone == "" {
		phone = respData.Get("buyer_logon_id")
	}
	logs.Info(fundBillList)

	var uInfo *users.UserModel
	var isDraw, isTianhai int
	placeInfo := dao.NewPlaceDao().GetPlaceById(devInfo.PlaceId).Unwrap().(*placemodel.PlaceModel)     // 获取网点详情
	userInfo := dao.NewUserDao().GetUserInfoByPlaceId(devInfo.PlaceId).Unwrap().(*users.UserModel) // 获取用户详情
	fmt.Println("uInfo", userInfo)
	uInfo = dao.GetParentUserInfoById(userInfo)

	fmt.Println("PloyWxOrder-isDraw", memInfo)
	fmt.Println("PloyWxOrder-isDraw", ployInfo)
	fmt.Println("PloyWxOrder-isDraw", memInfo, ployInfo, placeInfo)

	if openIsDraw > 0 {
		isDraw = logic.NewNotifyLogic().PloyWxOrder(memInfo, ployInfo, placeInfo)
		if isDraw == 1 {
			if uInfo.ID == 0 { // 代理商被删除，不存在
				uInfo = dao.NewUserDao().GetUserInfoById(2).Unwrap().(*users.UserModel)
			} else {
				u := dao.GetLastDrawUserInfo(uInfo)                                  // 获取开启权益的用户
				if u.ParentID == 0 && u.IsAdmin == 2 && placeInfo.BranchUserId > 0 { // 代理商都没开启
					uInfo = dao.NewUserDao().GetUserInfoById(placeInfo.BranchUserId).Unwrap().(*users.UserModel)
				} else {
					uInfo = u
				}
			}
		} else if isDraw == 2 {
			isDraw = 1
			isTianhai = 8
			uInfo = dao.NewUserDao().GetUserInfoById(2).Unwrap().(*users.UserModel)
		}
	}


	// 查询当前商户属于哪个代理商或运营商
	//agentID := wxLogic.GetParentUserInfoById(userInfo.ParentID)
	//if agentID == 0 {
	//	agentID = 2
	//}
	//log.Println("代理商ID", agentID)
	// 1:等待下单2:使用中3:已撤销4:交易失败5:已完成6:支付超时7:待守约10:已删除
	var status int8
	var tradeStateDesc string
	switch respData.Get("trade_status") {
	case "TRADE_SUCCESS":
		status = 2 // SUCCESS—支付成功  工作中
		tradeStateDesc = "交易支付成功"
	case "TRADE_CLOSED":
		status = 4 // PAYERROR--支付失败(其他原因，如银行返回失败)
		tradeStateDesc = "未付款交易超时关闭，或支付完成后全额退款"
	case "TRADE_FINISHED":
		status = 9 // CLOSED—已关闭
		tradeStateDesc = "交易结束，不可退款"
	case "WAIT_BUYER_PAY":
		status = 8 // USERPAYING--用户支付中
		tradeStateDesc = "交易创建，等待买家付款"

	}

	var payForm int8
	payForm = 2
	//if respData.Get("trade_type") == "JSAPI" || respData.Get("trade_type") == "Normal" {
	//	payForm = 2
	//}
	//if respData.Get("trade_type") == "PreAuthPay" {
	//	payForm = 1
	//}

	//解密公共参数
	params, err := url.ParseQuery(respData.Get("passback_params"))
	if err != nil {
		log.Println("解密公共参数失败", err.Error())
		return false
	}
	paramMap := map[string]string{}
	for key, value := range params {
		paramMap[key] = value[0]
	}

	fmt.Println("orders.New().Mutate", paramMap)

	m := orders.New().Mutate(
		orders.WithAppid(respData.Get("app_id")),
		orders.WithDeviceSn(paramMap["device_info"]),
		orders.WithMchid(respData.Get("seller_id")),
		orders.WithOpenid(respData.Get("buyer_open_id")),
		orders.WithOutTradeNo(respData.Get("trade_no")),  // 微信订单号
		orders.WithTradeNo(respData.Get("out_trade_no")), // 商户订单号
		orders.WithPayAt(dingo.Time(stamp.Unix())),       // 支付时间
		orders.WithTradeType(fundBillList.FundChannel), // 订单支付类型
		orders.WithMoney(money),
		orders.WithMoneyStr(decimal.NewFromInt(money).Div(decimal.NewFromInt(100)).StringFixed(2)),
		orders.WithTradeState(respData.Get("trade_status")), // 微信交易 状态
		orders.WithTradeStateDesc(tradeStateDesc),           // 微信交易状态描述
		orders.WithCreateAt(dingo.Time(time.Now().Unix())),
		orders.WithBeginAt(dingo.Time(time.Now().Unix())),
		orders.WithState(status),
		orders.WithOrderFrom("zhifubao"),
		orders.WithPayFrom(payForm), // 1免押 2押金
		orders.WithMemberId(memInfo.UUID),
		orders.WithMemberName(memInfo.NickName),
		orders.WithMemberPhone(phone),
		orders.WithPlaceId(devInfo.PlaceId),
		orders.WithPlaceName(devInfo.PlaceName),
		orders.WithSharedMode(devInfo.SharedMode),
		orders.WithPayMoney(payMoney),
		orders.WithPayMoneyStr(decimal.NewFromInt(payMoney).Div(decimal.NewFromInt(100)).StringFixed(2)),
		orders.WithTitle(respData.Get("subject")),
		orders.WithIsDraw(int8(isDraw)), // 1抽单 0不抽单
		orders.WithProductId(paramMap["attach"]),
		orders.WithFeeMode(int8(devInfo.FeeMode)),

		orders.WithIsTianHai(int8(isTianhai)), // 0新系统  1天海
		orders.WithUserId(userInfo.ID),
		orders.WithUserName(userInfo.Name),
		orders.WithParentId(userInfo.ParentID),
		orders.WithKaUserId(userInfo.BranchUserId),
		orders.WithAgentUserId(uInfo.ID),
		orders.WithPayType(3),
		orders.WithSettlementWay(1),           // 未结算
		orders.WithProdType(devInfo.ProdType), // 设备类型  1  2  3
		//orders.WithKaUserId(userInfo.ID), //分公司用户
	)
	if ok := dao.NewOrderDao().InsertOrder(m).Unwrap().(bool); ok { // 订单入库成功
		return true
	}
	return false
}

// 周期未授权-普通订单
func CreateOrderSingNoDraw(respData alipay.BodyMap, devInfo *devices.DeviceType, memInfo *membermodel.MembersModel, productId string) bool {
	stamp, _ := time.ParseInLocation("2006-01-02 15:04:05", respData.Get("notify_time"), time.Local)
	moneyFloat, _ := strconv.ParseFloat(respData.Get("total_amount"), 64)
	money := int64(moneyFloat * 100)
	payMoneyFloat, _ := strconv.ParseFloat(respData.Get("buyer_pay_amount"), 64)
	payMoney := int64(payMoneyFloat * 100)

	fundBillList := &struct {
		Amount string `json:"amount"`
		FundChannel   string `json:"fundChannel"`
	}{}
	_ = json.Unmarshal([]byte(respData.Get("fund_bill_list")), fundBillList)
	var phone string
	if memInfo.Phone == "" {
		phone = respData.Get("buyer_logon_id")
	}
	logs.Info(fundBillList)

	var uInfo *users.UserModel
	userInfo := dao.NewUserDao().GetUserInfoByPlaceId(devInfo.PlaceId).Unwrap().(*users.UserModel) // 获取用户详情
	uInfo = dao.GetParentUserInfoById(userInfo)

	// 1:等待下单2:使用中3:已撤销4:交易失败5:已完成6:支付超时7:待守约10:已删除
	var status int8
	var tradeStateDesc string
	switch respData.Get("trade_status") {
	case "TRADE_SUCCESS":
		status = 2 // SUCCESS—支付成功  工作中
		tradeStateDesc = "交易支付成功"
	case "TRADE_CLOSED":
		status = 4 // PAYERROR--支付失败(其他原因，如银行返回失败)
		tradeStateDesc = "未付款交易超时关闭，或支付完成后全额退款"
	case "TRADE_FINISHED":
		status = 9 // CLOSED—已关闭
		tradeStateDesc = "交易结束，不可退款"
	case "WAIT_BUYER_PAY":
		status = 8 // USERPAYING--用户支付中
		tradeStateDesc = "交易创建，等待买家付款"

	}

	var payForm int8
	payForm = 2

	//解密公共参数
	params, err := url.ParseQuery(respData.Get("passback_params"))
	if err != nil {
		log.Println("解密公共参数失败", err.Error())
		return false
	}
	paramMap := map[string]string{}
	for key, value := range params {
		paramMap[key] = value[0]
	}

	fmt.Println("orders.New().Mutate", paramMap)

	m := orders.New().Mutate(
		orders.WithAppid(respData.Get("app_id")),
		orders.WithDeviceSn(devInfo.DeviceSn),
		orders.WithMchid(respData.Get("seller_id")),
		orders.WithOpenid(respData.Get("buyer_open_id")),
		orders.WithOutTradeNo(respData.Get("trade_no")),  // 微信订单号
		orders.WithTradeNo(respData.Get("out_trade_no")), // 商户订单号
		orders.WithPayAt(dingo.Time(stamp.Unix())),       // 支付时间
		orders.WithTradeType(fundBillList.FundChannel), // 订单支付类型
		orders.WithMoney(money),
		orders.WithMoneyStr(decimal.NewFromInt(money).Div(decimal.NewFromInt(100)).StringFixed(2)),
		orders.WithTradeState(respData.Get("trade_status")), // 微信交易 状态
		orders.WithTradeStateDesc(tradeStateDesc),           // 微信交易状态描述
		orders.WithCreateAt(dingo.Time(time.Now().Unix())),
		orders.WithBeginAt(dingo.Time(time.Now().Unix())),
		orders.WithState(status),
		orders.WithOrderFrom("zhifubao"),
		orders.WithPayFrom(payForm), // 1免押 2押金
		orders.WithMemberId(memInfo.UUID),
		orders.WithMemberName(memInfo.NickName),
		orders.WithMemberPhone(phone),
		orders.WithPlaceId(devInfo.PlaceId),
		orders.WithPlaceName(devInfo.PlaceName),
		orders.WithSharedMode(devInfo.SharedMode),
		orders.WithPayMoney(payMoney),
		orders.WithPayMoneyStr(decimal.NewFromInt(payMoney).Div(decimal.NewFromInt(100)).StringFixed(2)),
		orders.WithTitle(respData.Get("subject")),
		orders.WithIsDraw(1), // 1抽单 0不抽单
		orders.WithProductId(productId),
		orders.WithFeeMode(int8(devInfo.FeeMode)),
		orders.WithIsTianHai(8), // 0新系统  1天海
		orders.WithUserId(userInfo.ID),
		orders.WithUserName(userInfo.Name),
		orders.WithParentId(userInfo.ParentID),
		orders.WithKaUserId(userInfo.BranchUserId),
		orders.WithAgentUserId(uInfo.ID),
		orders.WithPayType(3),
		orders.WithSettlementWay(1),           // 未结算
		orders.WithProdType(devInfo.ProdType), // 设备类型  1  2  3
		//orders.WithKaUserId(userInfo.ID), //分公司用户
	)
	if ok := dao.NewOrderDao().InsertOrder(m).Unwrap().(bool); ok { // 订单入库成功
		return true
	}
	return false
}

func UpdateDeviceInfo(deviceSn string) bool {
	dm := devices.New().Mutate(
		devices.WithUpdateAt(dingo.Time(time.Now().Unix())),
		devices.WithStatus(3), //  3工作中
		devices.WithDeviceSn(deviceSn),
	)
	if ok := dao.NewDeviceDao().UpdateDeviceBySn(dm).Unwrap().(bool); ok {
		return true
	}
	return false
}

func HandleAliPayNotifyCommon(c *gin.Context) (bodyMap alipay.BodyMap, err error) {

	// 解析请求参数
	bm, err := alipay.ParseNotifyToBodyMap(c.Request)
	if err != nil {
		log.Println("支付宝统一下单,解析请求参数失败", err.Error())
		return
	}
	log.Println("异步通知数据", bm)

	file, err := ioutil.ReadFile(global.Cfg.Ali.PublicKey)
	if err != nil {
		log.Println("支付宝统一下单,获取应用密钥失败", err.Error())
		return
	}

	//var bodyMap alipay.BodyMap
	//aliPayPublicKey 支付宝公钥证书
	aliPayPublicKey := string(file)
	// 验签
	ok, err := alipay.VerifySign(aliPayPublicKey, bm)
	if err != nil {
		log.Println("验签失败", err.Error())
		return
	}
	bs, err := json.Marshal(bm)
	if ok {
		err = json.Unmarshal(bs, &bodyMap)
		if err != nil {
			log.Println("参数转换错误 ,HandleAliPayNotify", err.Error())
			return
		}
	}

	return
}

func AutomatePayResultNotify(c *gin.Context) {
	resultData, err := HandleAliPayNotifyCommon(c)
	fmt.Println("AutomatePayResultNotify", resultData)
	if err != nil || resultData.Get("out_trade_no") == "" {
		return
	}

	tradeNo := resultData.Get("out_trade_no")
	thirdTradeNo := resultData.Get("trade_no")

	param := &automate.OrderPayDb{
		OrderDb: automate.OrderDb{
			TradeNo:      tradeNo,
			ThirdTradeNo: thirdTradeNo,
			Status:       helper.TypeNumOrderAutomateStatusWaitSend,
		},
		PayTime: time.Now().Format("2006-01-02 15:04:05"),
	}

	orderData := dao.NewAutomateDaoDao().GetGoodsOrderInfoByTradeNo(tradeNo)
	orderInfo := orderData.Unwrap().(*request.GetGoodsOrderInfoByIdRes)
	if orderInfo.Status == helper.TypeNumOrderAutomateStatusWaitDone {
		param.Status = 0
	}

	if dao.NewAutomateDaoDao().UpdateGoodsOrder(param).Err != nil {
		return
	}

	c.JSON(200, "success")
}

func RoomPayResultNotify(c *gin.Context) {
	resultData, err := HandleAliPayNotifyCommon(c)
	fmt.Println("AutomatePayResultNotify", resultData)
	if err != nil || resultData.Get("out_trade_no") == "" {
		return
	}

	tradeNo := resultData.Get("out_trade_no")
	thirdTradeNo := resultData.Get("trade_no")
	amount, _ := strconv.Atoi(resultData.Get("cash_fee"))

	dataInfo := dao.NewRoomDaoDao().GetRoomOrderPlace(tradeNo)
	param := &placemodel.PlacesServiceNotification{
		MemberId:         dataInfo.MemberId,
		PlaceId:          dataInfo.PlaceId,
		PlaceName:        dataInfo.PlaceName,
		PlaceRoom:        dataInfo.Room,
		MemberPhone:      dataInfo.Phone,
		DeviceSn:         dataInfo.DeviceSn,
		NotificationType: helper.TypeNumNotificationTypeContinues,
		Status:           helper.TypeNumNotificationStatusWait,
		Info:             "房间续住",
		ServiceInfo:      []string{dataInfo.InTime, dataInfo.LeaveTime},
	}

	if notificationsInfo := logic.NewShWxNotificationsLogic().InitNotificationsData(param); notificationsInfo.Id <= 0 {
		return
	} else {
		updateParam := &room.OrderDb{
			Amount:         amount,
			TradeNo:        tradeNo,
			ThirdTradeNo:   thirdTradeNo,
			NotificationId: notificationsInfo.Id,
			Status:         helper.TypeNumRoomOrderStatusDoneWait,
		}
		if data := dao.NewRoomDaoDao().UpdateRoomOrder(updateParam); data.Err != nil {
			zap.L().Error("UpdateRoomOrder:" + data.Err.Error())
			return
		}
	}

	c.JSON(200, "success")
}

func GoodsPayResultNotify(c *gin.Context) {
	resultData, err := HandleAliPayNotifyCommon(c)
	fmt.Println("AutomatePayResultNotify", resultData)
	if err != nil || resultData.Get("out_trade_no") == "" {
		return
	}

	tradeNo := resultData.Get("out_trade_no")
	thirdTradeNo := resultData.Get("trade_no")
	orderList := dao.NewGoodsDao().GetGoodsOrdersListByTradeNo(tradeNo, 0).Unwrap().([]*goods.OrderUpdate)
	if len(orderList) == 0 {
		return
	}
	param := &placemodel.PlacesServiceNotification{
		MemberId:         orderList[0].MemberId,
		PlaceId:          orderList[0].PlaceId,
		UserId:           orderList[0].UserId,
		PlaceName:        orderList[0].PlaceName,
		PlaceRoom:        orderList[0].Address,
		DeviceSn:         orderList[0].DeviceSn,
		NotificationType: helper.TypeNumNotificationTypeGoods,
		Status:           helper.TypeNumNotificationStatusWait,
		Info:             "超市服务",
		Message:          orderList[0].Message,
		MemberPhone:      memberdao.NewMemberDao().GetMemberInfoById(orderList[0].MemberId).Unwrap().(*membermodel.MembersModel).Phone,
	}
	if notificationsInfo := logic.NewShWxNotificationsLogic().InitNotificationsData(param); notificationsInfo.Id <= 0 {
		return
	} else {
		params := &goods.OrderUpdate{
			TradeNo:        tradeNo,
			ThirdTradeNo:   thirdTradeNo,
			NotificationId: notificationsInfo.Id,
			Status:         helper.TypeNumGoodsOrderStatusDonePay,
		}
		if err = dao.NewGoodsDao().UpdateGoodsOrders(params); err != nil {
			zap.L().Error(err.Error())
			return
		}
	}

	c.JSON(200, "success")
}
